package com.baiqian.doupo.event;

import com.baiqian.doupo.DouPo;
import com.baiqian.doupo.Utils;
import com.baiqian.doupo.capability.DouPoModCapability;
import com.baiqian.doupo.capability.douqi.DouQiCapabilityProvider;
import com.baiqian.doupo.capability.douqi.IDouQiCapability;
import com.baiqian.doupo.command.*;
import com.baiqian.doupo.douji.DouJi;
import com.baiqian.doupo.douji.DouJi_HuoDing;
import com.baiqian.doupo.effect.EffectRegistry;
import com.baiqian.doupo.network.Networking;
import com.baiqian.doupo.network.SendPack;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.DoubleArgumentType;
import com.mojang.brigadier.tree.LiteralCommandNode;
import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.potion.EffectInstance;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.EntityLeaveWorldEvent;
import net.minecraftforge.event.entity.living.LivingDamageEvent;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.entity.player.PlayerXpEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.network.PacketDistributor;
import org.apache.logging.log4j.LogManager;

import static com.baiqian.doupo.KeyBoradSave.keyG;
import static com.baiqian.doupo.KeyBoradSave.keyH;

@Mod.EventBusSubscriber()
public class ModEventHandler {


    private static int beforeExp = 0;

    @SubscribeEvent
    public static void onLoadPlayer(PlayerEvent.PlayerLoggedInEvent event) {//玩家初载入:仅服务器
        beforeExp = event.getPlayer().experienceLevel;
    }

    @SubscribeEvent
    public static void onLevelChange(PlayerXpEvent.LevelChange event) {//等级变更
        PlayerEntity player = event.getPlayer();
        LazyOptional<IDouQiCapability> douQiCap = player.getCapability(DouPoModCapability.DOUQI_CAPABILTTY);
        douQiCap.ifPresent((l) -> {
            if (l.getLevelBig() == 0 && player.experienceLevel < 30) {
                switch (player.experienceLevel + 1) {
                    case 1: {
                        player.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".xp_1_" + (beforeExp < 1 ? "before" : "after")), player.getUniqueID());
                        break;
                    }
                    case 10: {
                        player.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".xp_2_" + (beforeExp < 10 ? "before" : "after")), player.getUniqueID());
                        break;
                    }
                    case 20: {
                        player.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".xp_3_" + (beforeExp < 20 ? "before" : "after")), player.getUniqueID());
                        break;
                    }
                    case 30: {
                        player.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".xp_4_" + (beforeExp < 30 ? "before" : "after")), player.getUniqueID());
                        break;
                    }
                }
                beforeExp = player.experienceLevel;
            }
        });
    }

    @SubscribeEvent
    public static void onLivingHurtEvent(LivingHurtEvent event) {//我方伤害抵消
        if (event.getEntity() instanceof PlayerEntity) {
            PlayerEntity player_entity = (PlayerEntity) event.getEntity();
            LazyOptional<IDouQiCapability> douqiCap = player_entity.getCapability(DouPoModCapability.DOUQI_CAPABILTTY);
            if (douqiCap.isPresent())
                douqiCap.ifPresent((l) -> {
                            if (l.getLevelBig() >= 6) {//起码是个斗王
                                if (event.getSource().damageType.equals(DamageSource.FALL.getDamageType())) {//如果是掉落伤害
                                    if (player_entity.abilities.allowFlying) {//如果开了允许飞行
                                        event.setAmount(0);//无伤害
                                        return;
                                    }
                                }
                            }
                            double baseDefense = l.getBaseDefense();
                            if (baseDefense >= event.getAmount())//肉身防御足以对抗伤害
                                event.setAmount(0);
                            else {//需要斗气防御才能对抗伤害
                                double defense = l.getDefense();//获得当前的完全防御
                                l.addDouQi(-l.getMaxDouQiPay(), 0, true, player_entity);//消耗斗气
                                event.setAmount((float) Math.max(0, event.getAmount() - defense));
                            }
                        }
                );
        }
    }

    @SubscribeEvent
    public static void onLivingDamageEvent(LivingDamageEvent event) {//我方攻击加成
        if (event.getSource().getImmediateSource() instanceof PlayerEntity) {
            LazyOptional<IDouQiCapability> douqiCap = event.getSource().getImmediateSource().getCapability(DouPoModCapability.DOUQI_CAPABILTTY);
            if (douqiCap.isPresent())
                douqiCap.ifPresent((l) -> {
                    for (int i = 0; i < 4; ++i) {
                        int j = l.getDouJiGroup()[l.getDouJiGroupChoose() * 4 + i];
                        if (j != -1) {//如果斗技存在
                            DouJi douji = l.getDouJis().get(j);
                            if (douji.use_time > 0 || douji.use_time == -1) {//且正在使用
                                if (douji.douji_type == 3)//还是个附加攻击型
                                    douji.addEffect(event.getEntityLiving());
                            }
                        }
                    }
                    double damage = l.getDamage();//获得当前的完全攻击
                    l.addDouQi(-l.getMaxDouQiPay(), 0, true, (PlayerEntity) event.getSource().getImmediateSource());//消耗斗气
                    event.setAmount((float) (event.getAmount() + damage));
                });
        }
    }

    @SubscribeEvent
    public static void onServerStaring(RegisterCommandsEvent event) {//输入指令
        CommandDispatcher<CommandSource> dispatcher = event.getDispatcher();
        /*
         * 关于hasPermissionLevel
         * 等级一共分四种，对应的数字为1、2、3和4
         * 等级为1代表任何玩家都可以执行，比如/ping这样的命令
         * 等级为2代表命令方块可以执行，而等级4，则只有这个服务器的OP、还有单人模式下的作弊玩家可以执行。
         * */
        //重生
        LiteralCommandNode<CommandSource> cmd = dispatcher.register(
                Commands.literal(Utils.MOD_ID)
                        .requires((commandSource) -> commandSource.hasPermissionLevel(4))
                        .then(
                                Commands.literal("rebirth")
                                        .executes(ReBirthCommand.instance)
                        )
        );
        dispatcher.register(Commands.literal("dp").redirect(cmd));
        //设置斗气提纯程度
        cmd = dispatcher.register(
                Commands.literal(Utils.MOD_ID)
                        .requires((commandSource) -> commandSource.hasPermissionLevel(4))
                        .then(
                                Commands.literal("width").then(
                                        Commands.literal("set").then(
                                                Commands.argument("number", DoubleArgumentType.doubleArg(0.0))
                                                        .executes(SetWidthCommand.instance)
                                        )
                                )
                        )
        );
        dispatcher.register(Commands.literal("dp").redirect(cmd));
        //设置斗气
        cmd = dispatcher.register(
                Commands.literal(Utils.MOD_ID)
                        .requires((commandSource) -> commandSource.hasPermissionLevel(4))
                        .then(
                                Commands.literal("douqi").then(
                                        Commands.literal("set").then(
                                                Commands.argument("number", DoubleArgumentType.doubleArg(0.0))
                                                        .executes(SetDouQiCommand.instance)
                                        )
                                )
                        )
        );
        dispatcher.register(Commands.literal("dp").redirect(cmd));
        //设置灵魂强度
        cmd = dispatcher.register(
                Commands.literal(Utils.MOD_ID)
                        .requires((commandSource) -> commandSource.hasPermissionLevel(4))
                        .then(
                                Commands.literal("soul").then(
                                        Commands.literal("set").then(
                                                Commands.argument("number", DoubleArgumentType.doubleArg(0.0))
                                                        .executes(SetSoulCommand.instance)
                                        )
                                )
                        )
        );
        dispatcher.register(Commands.literal("dp").redirect(cmd));
        //设置灵魂最大强度
        cmd = dispatcher.register(
                Commands.literal(Utils.MOD_ID)
                        .requires((commandSource) -> commandSource.hasPermissionLevel(4))
                        .then(
                                Commands.literal("soul_max").then(
                                        Commands.literal("set").then(
                                                Commands.argument("number", DoubleArgumentType.doubleArg(0.0))
                                                        .executes(SetSoulMaxCommand.instance)
                                        )
                                )
                        )
        );
        dispatcher.register(Commands.literal("dp").redirect(cmd));
        //增加斗气提纯程度
        cmd = dispatcher.register(
                Commands.literal(Utils.MOD_ID)
                        .requires((commandSource) -> commandSource.hasPermissionLevel(4))
                        .then(
                                Commands.literal("width").then(
                                        Commands.literal("add").then(
                                                Commands.argument("number", DoubleArgumentType.doubleArg(0.0))
                                                        .executes(AddWidthCommand.instance)
                                        )
                                )
                        )
        );
        dispatcher.register(Commands.literal("dp").redirect(cmd));
        //增加斗气
        cmd = dispatcher.register(
                Commands.literal(Utils.MOD_ID)
                        .requires((commandSource) -> commandSource.hasPermissionLevel(4))
                        .then(
                                Commands.literal("douqi").then(
                                        Commands.literal("add").then(
                                                Commands.argument("number", DoubleArgumentType.doubleArg(0.0))
                                                        .executes(AddDouQiCommand.instance)
                                        )
                                )
                        )
        );
        dispatcher.register(Commands.literal("dp").redirect(cmd));
        //增加灵魂强度
        cmd = dispatcher.register(
                Commands.literal(Utils.MOD_ID)
                        .requires((commandSource) -> commandSource.hasPermissionLevel(4))
                        .then(
                                Commands.literal("soul").then(
                                        Commands.literal("add").then(
                                                Commands.argument("number", DoubleArgumentType.doubleArg(0.0))
                                                        .executes(AddSoulCommand.instance)
                                        )
                                )
                        )
        );
        dispatcher.register(Commands.literal("dp").redirect(cmd));
        //增加灵魂最大强度
        cmd = dispatcher.register(
                Commands.literal(Utils.MOD_ID)
                        .requires((commandSource) -> commandSource.hasPermissionLevel(4))
                        .then(
                                Commands.literal("soul_max").then(
                                        Commands.literal("add").then(
                                                Commands.argument("number", DoubleArgumentType.doubleArg(0.0))
                                                        .executes(AddSoulMaxCommand.instance)
                                        )
                                )
                        )
        );
        dispatcher.register(Commands.literal("dp").redirect(cmd));
        //增加等级
        cmd = dispatcher.register(
                Commands.literal(Utils.MOD_ID)
                        .requires((commandSource) -> commandSource.hasPermissionLevel(4))
                        .then(
                                Commands.literal("level").then(
                                        Commands.literal("add")
                                                .executes(AddLevelCommand.instance)
                                )
                        )
        );
        dispatcher.register(Commands.literal("dp").redirect(cmd));
        //展示异火
        cmd = dispatcher.register(
                Commands.literal(Utils.MOD_ID)
                        .requires((commandSource) -> commandSource.hasPermissionLevel(0))
                        .then(
                                Commands.literal("show").then(
                                        Commands.literal("fire")
                                                .executes(ShowFire.instance)
                                )
                        )
        );
        dispatcher.register(Commands.literal("dp").redirect(cmd));
    }

    @SubscribeEvent//给实体附加能力
    public static void onAttachCapabilityEvent(AttachCapabilitiesEvent<Entity> event) {//客户端服务端都会执行
        Entity entity = event.getObject();
        if (entity instanceof PlayerEntity) {//如果实体是玩家
            event.addCapability(new ResourceLocation(Utils.MOD_ID, "douqi"), new DouQiCapabilityProvider());
        }
    }

    /**
     * 方块扫描已经进行了多久tick
     */
    private static int scan_block_tick = 0;

    @SubscribeEvent//只要进入世界就会一直运行的事件
    public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event) {//服务端与客户端
        if (!event.side.isClient()) {
            PlayerEntity player = event.player;
            World world = event.player.world;
            LazyOptional<IDouQiCapability> douqiCap = player.getCapability(DouPoModCapability.DOUQI_CAPABILTTY);
            if (douqiCap.isPresent()) {
                douqiCap.ifPresent((l) -> {
                            if (l.isToLevelBig() || l.isToLevelMiddle() || l.isToLevelSmall()) {//如果是进阶中
                                player.addPotionEffect(new EffectInstance(EffectRegistry.ju_jing_hui_shen.get(), 3, 255, false, false, false));
                                l.addLevelUpTime(1);//进阶时间+1
                                LogManager.getLogger().info(l.getLevelUpTime());
                                if (l.getLevelUpTime() > l.getLevelUpTimeMax() || DouPo.Debug) {
                                    l.setLevelUpTime(0);
                                    l.addDouQiLevel(player);
                                    if (l.isToLevelBig()) {//大境界晋级成功
                                        switch (l.getLevelBig()) {
                                            case 2:
                                                player.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_2_end_good"), player.getUniqueID());
                                                break;
                                            default:
                                                player.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_default_end_good", l.getDouQiLevelStr()), player.getUniqueID());
                                                break;
                                        }
                                        l.isToLevelBig(false);
                                        if (l.getLevelBig() == 2) {//如果晋级后是斗者
                                            if (l.getSoulPropertyMain() == 1 && l.getSoulProperty()[3] || DouPo.Debug) {//且灵魂属性合规
                                                boolean flag = true;
                                                for (com.baiqian.doupo.douji.DouJi douji : l.getDouJis())
                                                    if (douji.douji_name.equals("火鼎")) {
                                                        flag = false;
                                                        break;
                                                    }
                                                if (flag)
                                                    l.addDouJi(new DouJi_HuoDing());
                                            }
                                        }
                                    } else if (l.isToLevelMiddle()) {
                                        player.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_default_end_good", l.getDouQiLevelStr()), player.getUniqueID());
                                        l.isToLevelMiddle(false);
                                    } else if (l.isToLevelSmall()) {
                                        player.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_default_end_good", l.getDouQiLevelStr()), player.getUniqueID());
                                        l.isToLevelSmall(false);
                                    }
                                    l.setDouQiHaveMax(l.getDouQi(1), player);
                                    l.tryToUpLevel(player);
                                }
                                else {
                                    //突破等级该tick所需要的斗气量
                                    l.addDouQi(-l.getDouQiLevelUpPay(), 2, true, player);
                                }
                            } else {
                                //没有进阶
                                //此处应当遍历修炼按钮的情况，并给相应的角色进行修炼
                                try {
                                    if (keyG.get(player.getUniqueID()) > 0) {
                                        keyG.put(player.getUniqueID(), keyG.get(player.getUniqueID()) - 1);
//                                        l.updateWorldAttr(player, world);
                                        l.addDouQi(player);
                                        player.addPotionEffect(new EffectInstance(EffectRegistry.ju_jing_hui_shen.get(), 3, 255, false, false, false));
                                    }
                                    if (keyH.get(player.getUniqueID()) > 0) {
                                        keyH.put(player.getUniqueID(), keyH.get(player.getUniqueID()) - 1);
                                        l.addDouQiCompress(player);
                                    }
                                } catch (NullPointerException nullPointerException) {
                                    keyG.put(player.getUniqueID(), 0);
                                    keyH.put(player.getUniqueID(), 0);
                                    //没有该角色修炼过的痕迹
                                }
                                l.tryToUpLevel(player);//用于当斗气在非修炼情况下满溢时进阶用
                                l.loseDouQiCompress(player);
                                l.addSoul();
                            }
                            //如果已经展开斗气化翼
                            if (l.isFlying()) {
                                if(!player.abilities.isCreativeMode){
                                    if(player.abilities.isFlying){
                                        if (l.getDouQi(0) < 2.5) {
                                            player.abilities.allowFlying=false;
                                            player.abilities.isFlying=false;
                                            l.isFlying(!l.isFlying());
                                            Networking.INSTANCE.send(
                                                    PacketDistributor.PLAYER.with(
                                                            () -> (ServerPlayerEntity) player
                                                    ),
                                                    new SendPack(2,l.serializeNBT()));
                                            player.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".press_SPACE_to_have_not"), player.getUniqueID());
                                        } else {
                                            l.addDouQi(-2.5, 0, true, player);
                                        }
                                    }
                                }
                            }
                            if (l.getSoulPercentage() < 0.2) {//灵魂疲惫
                                player.addPotionEffect(new EffectInstance(EffectRegistry.ling_hun_pi_bei.get(), 5, (int) (5 - l.getSoul() * 10) * 2, false, false, false));
                            }
                            if (l.getSoul() < 0.1) {//灵魂枯竭
                                player.addPotionEffect(new EffectInstance(EffectRegistry.ling_hun_ku_jie.get(), 5, (int) (50 - l.getSoul() * 1000) * 4, false, false, false));
                            }
                            if (l.isScaningBlock()) {
                                ++scan_block_tick;
                                if (scan_block_tick > 20 * 20) {//如果已经进行了20s的方块扫描
                                    scan_block_tick = 0;
                                    l.isScaningBlock(false);//停止方块扫描，重新开始
                                }
                            } else
                                scan_block_tick = 0;
                            //每10s扫一次
                            if(System.currentTimeMillis()/1000%10==0){
                                l.updateWorldAttr(player, world);
                            }
                            for (DouJi dou_ji : l.getDouJis()) {
                                if (dou_ji.is_use_time_ing(l)) {//试图减少使用时间
                                    dou_ji.use(l, player);//激发使用效果(包含技能消耗)
                                }
                                dou_ji.isRebirthing();//试图减少冷却时间
                            }
                            //将当前玩家的状态发送回客户端
                            Networking.INSTANCE.send(
                                    PacketDistributor.PLAYER.with(
                                            () -> (ServerPlayerEntity) player
                                    ), new SendPack(0, l.serializeNBT()));
                        }
                );
            }
        }

    }

    @SubscribeEvent//当玩家死亡后重生或者从末地回到主世界，都会触发这个方法
    public static void onPlayerCloned(PlayerEvent.Clone event) {//只会在服务端执行
        if (event.isWasDeath()) {//死亡重生
            if (event.getPlayer().world.getGameRules().getBoolean(GameRules.KEEP_INVENTORY)) {
                LazyOptional<IDouQiCapability> oldDouQiCap = event.getOriginal().getCapability(DouPoModCapability.DOUQI_CAPABILTTY);
                LazyOptional<IDouQiCapability> newDouQiCap = event.getPlayer().getCapability(DouPoModCapability.DOUQI_CAPABILTTY);
                if (oldDouQiCap.isPresent() && newDouQiCap.isPresent()) {
                    newDouQiCap.ifPresent((newCap) -> oldDouQiCap.ifPresent((oldCap) -> newCap.deserializeNBT(oldCap.serializeNBT())));
                }
            }
        } else {//末地归来
            LazyOptional<IDouQiCapability> oldDouQiCap = event.getOriginal().getCapability(DouPoModCapability.DOUQI_CAPABILTTY);
            LazyOptional<IDouQiCapability> newDouQiCap = event.getPlayer().getCapability(DouPoModCapability.DOUQI_CAPABILTTY);
            if (oldDouQiCap.isPresent() && newDouQiCap.isPresent()) {
                newDouQiCap.ifPresent((newCap) -> oldDouQiCap.ifPresent((oldCap) -> newCap.deserializeNBT(oldCap.serializeNBT())));
            }
        }
    }


    @SubscribeEvent//当玩家死亡后重生或者从末地回到主世界，都会触发这个方法
    public static void onEntityLeaveWorldEvent(EntityLeaveWorldEvent event) {//只会在服务端执行
        if (event.getEntity() instanceof PlayerEntity) {
            if (event.getWorld().isRemote) {
                LogManager.getLogger().info(event.getEntity().getName());
            }
        }
    }

}
